C++键值对(pair)和元组(tuple)

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  本教程将从 C++ 键值对(pair)和元组(tuple)的核心概念、特性入手,详细讲解两者的定义、初始化、访问方式及典型应用场景,帮助你掌握这两种轻量级复合数据类型的核心用法。

教程目录导航

一、pair和tuple核心概述

1.1 键值对(pair)的概念与特点

C++ 中的 std::pair 是定义在 <utility> 头文件中的轻量级复合数据类型,用于封装两个不同类型的元素(也可相同),形成“键-值”(key-value)映射关系,是 C++ 标准库中最基础的复合类型之一。

pair 的核心特点:

1.2 元组(tuple)的概念与特点

C++ 中的 std::tuple 是定义在 <tuple> 头文件中的通用复合数据类型,是 pair 的“升级版”,用于封装任意数量、任意类型的元素,实现多维度数据的聚合。

tuple 的核心特点:

1.3 pair与tuple的核心区别

特点 std::pair std::tuple
元素数量 固定2个 任意数量(0+)
访问方式 通过 first/second 直接访问 通过 std::get<索引>() 模板函数访问
头文件 <utility> <tuple>
适用场景 二元键值映射(如map元素、简单数据配对) 多维度数据聚合(如多字段记录、多值返回)
底层关系 可视为特殊的 tuple(tuple<T1, T2>) 通用化的复合类型,包含 pair 的能力

二、键值对(pair)的核心应用

2.1 pair的定义与初始化

使用 pair 前需包含头文件 #include <utility>(STL容器头文件通常会间接包含,可省略),支持多种初始化方式:

方式 1:默认构造 + 手动赋值


#include <iostream>
#include <utility>   // pair核心头文件
#include <string>
using namespace std;

int main() {
    // 默认构造:元素值为对应类型的默认值
    pair<int, string> p1;
    // 手动赋值
    p1.first = 101;    // 第一个元素(键)
    p1.second = "张三"; // 第二个元素(值)
    
    cout << "p1: " << p1.first << " - " << p1.second << endl;
    return 0;
}
        

方式 2:构造函数直接初始化


int main() {
    // 直接传入两个元素初始化
    pair<int, string> p2(102, "李四");
    pair<double, bool> p3(98.5, true);
    
    cout << "p2: " << p2.first << " - " << p2.second << endl;
    cout << "p3: " << p3.first << " - " << boolalpha << p3.second << endl;
    return 0;
}
        

方式 3:使用 make_pair 函数(自动推导类型)


int main() {
    // make_pair自动推导元素类型,无需显式指定
    auto p4 = make_pair(103, "王五");
    auto p5 = make_pair(3.14, "圆周率");
    
    cout << "p4: " << p4.first << " - " << p4.second << endl;
    cout << "p5: " << p5.first << " - " << p5.second << endl;
    return 0;
}
        

2.2 pair成员的访问方式

pair 的两个元素通过 firstsecond 直接访问,支持读写操作:


int main() {
    pair<string, int> p = make_pair("苹果", 5);
    
    // 读取成员
    cout << "商品:" << p.first << ",价格:" << p.second << endl;
    
    // 修改成员
    p.second = 6;  // 修改价格
    cout << "修改后:" << p.first << ",价格:" << p.second << endl;
    
    return 0;
}
        

2.3 pair的典型应用场景

场景 1:作为 map/unordered_map 的元素

STL 中的 map 容器底层以 pair 为存储单元,key 对应 pair.first,value 对应 pair.second:


#include <iostream>
#include <map>   // map头文件
#include <string>
using namespace std;

int main() {
    // map的每个元素都是pair<const key, value>
    map<int, string> stuMap;
    
    // 插入pair元素
    stuMap.insert(pair<int, string>(101, "张三"));
    stuMap.insert(make_pair(102, "李四"));
    stuMap[103] = "王五";  // 简化赋值(底层仍为pair)
    
    // 遍历map,访问pair元素
    for (const auto& p : stuMap) {
        cout << "学号:" << p.first << ",姓名:" << p.second << endl;
    }
    
    return 0;
}
        

场景 2:函数返回多个值(二元)

利用 pair 实现函数返回两个不同类型的值:


#include <iostream>
#include <utility>
#include <string>
using namespace std;

// 返回学生的(姓名,成绩)
pair<string, float> getStudentInfo() {
    return make_pair("赵六", 92.5);
}

int main() {
    auto [name, score] = getStudentInfo(); // C++17结构化绑定(简化访问)
    cout << "姓名:" << name << ",成绩:" << score << endl;
    
    // 兼容低版本C++的写法
    pair<string, float> info = getStudentInfo();
    cout << "姓名:" << info.first << ",成绩:" << info.second << endl;
    
    return 0;
}
        

场景 3:数据配对存储(如坐标、区间)


#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int main() {
    // 存储多个坐标点(x,y)
    vector<pair<int, int>> points;
    points.push_back(make_pair(1, 2));
    points.push_back(make_pair(3, 4));
    points.push_back(make_pair(5, 6));
    
    // 遍历坐标
    for (const auto& p : points) {
        cout << "坐标(" << p.first << ", " << p.second << ")" << endl;
    }
    
    return 0;
}
        

三、元组(tuple)的核心应用

3.1 tuple的定义与初始化

使用 tuple 前需包含头文件 #include <tuple>,支持多种初始化方式:

方式 1:构造函数显式初始化


#include <iostream>
#include <tuple>   // tuple核心头文件
#include <string>
using namespace std;

int main() {
    // 显式指定类型:tuple<类型1, 类型2, 类型3...>
    tuple<int, string, float, bool> t1(101, "张三", 92.5, true);
    
    cout << "学号:" << get<0>(t1) << endl;  // 索引从0开始
    cout << "姓名:" << get<1>(t1) << endl;
    return 0;
}
        

方式 2:使用 make_tuple 函数(自动推导类型)


int main() {
    // make_tuple自动推导类型,简化写法
    auto t2 = make_tuple(102, "李四", 88.0, false);
    auto t3 = make_tuple("苹果", 5.99, 100); // 字符串、浮点数、整数
    
    cout << "商品:" << get<0>(t3) << ",单价:" << get<1>(t3) << ",库存:" << get<2>(t3) << endl;
    return 0;
}
        

方式 3:tuple的默认构造与赋值


int main() {
    // 默认构造:元素为对应类型默认值
    tuple<string, int, double> t4;
    // 赋值
    t4 = make_tuple("香蕉", 3, 2.99);
    
    cout << "赋值后:" << get<0>(t4) << " - " << get<1>(t4) << " - " << get<2>(t4) << endl;
    return 0;
}
        

3.2 tuple元素的访问方式

方式 1:使用 std::get<索引>(tuple) 访问

索引必须是编译期常量(字面量或constexpr变量),支持读写操作:


int main() {
    auto t = make_tuple("赵六", 17, 90.0, "男");
    
    // 读取元素(索引从0开始)
    cout << "姓名:" << get<0>(t) << endl;
    cout << "年龄:" << get<1>(t) << endl;
    cout << "成绩:" << get<2>(t) << endl;
    cout << "性别:" << get<3>(t) << endl;
    
    // 修改元素
    get<2>(t) = 95.5;
    cout << "修改后成绩:" << get<2>(t) << endl;
    
    return 0;
}
        

方式 2:C++17结构化绑定(简化多元素访问)


int main() {
    auto t = make_tuple("孙七", 18, 85.5, "女", 104);
    
    // 结构化绑定:一次性解包所有元素
    auto [name, age, score, gender, id] = t;
    cout << "学号:" << id << ",姓名:" << name << ",年龄:" << age 
         << ",成绩:" << score << ",性别:" << gender << endl;
    
    return 0;
}
        

3.3 tuple的常用操作

操作 1:获取tuple的元素数量(tuple_size)


#include <iostream>
#include <tuple>
#include <string>
using namespace std;

int main() {
    auto t = make_tuple(1, "hello", 3.14);
    
    // 获取元素数量(编译期常量)
    constexpr size_t size = tuple_size<decltype(t)>::value;
    cout << "tuple元素数量:" << size << endl; // 输出3
    
    return 0;
}
        

操作 2:tuple的拼接(tuple_cat)


#include <iostream>
#include <tuple>
#include <string>
using namespace std;

int main() {
    auto t1 = make_tuple(101, "张三");
    auto t2 = make_tuple(92.5, "男");
    
    // 拼接两个tuple
    auto t3 = tuple_cat(t1, t2);
    
    // t3包含4个元素:101, "张三", 92.5, "男"
    cout << get<0>(t3) << " - " << get<1>(t3) << " - " 
         << get<2>(t3) << " - " << get<3>(t3) << endl;
    
    return 0;
}
        

操作 3:tuple的比较运算


#include <iostream>
#include <tuple>
#include <string>
using namespace std;

int main() {
    auto t1 = make_tuple(1, 2, 3);
    auto t2 = make_tuple(1, 3, 2);
    auto t3 = make_tuple(1, 2, 3);
    
    cout << boolalpha;
    cout << "t1 == t2: " << (t1 == t2) << endl; // false
    cout << "t1 == t3: " << (t1 == t3) << endl; // true
    cout << "t1 < t2: " << (t1 < t2) << endl;   // true(按索引依次比较)
    
    return 0;
}
        

3.4 tuple的典型应用场景

场景 1:函数返回多个不同类型的值


#include <iostream>
#include <tuple>
#include <string>
using namespace std;

// 返回学生的(学号、姓名、成绩、是否及格)
tuple<int, string, float, bool> getStudentDetail() {
    int id = 105;
    string name = "周八";
    float score = 88.5;
    bool pass = score >= 60;
    
    return make_tuple(id, name, score, pass);
}

int main() {
    // 结构化绑定解包
    auto [id, name, score, pass] = getStudentDetail();
    cout << "学号:" << id << endl;
    cout << "姓名:" << name << endl;
    cout << "成绩:" << score << endl;
    cout << "是否及格:" << boolalpha << pass << endl;
    
    return 0;
}
        

场景 2:存储多维度复合数据


#include <iostream>
#include <tuple>
#include <vector>
#include <string>
using namespace std;

int main() {
    // 存储商品信息:(名称、单价、库存、是否上架)
    vector<tuple<string, double, int, boo>> goods;
    goods.push_back(make_tuple("手机", 2999.99, 50, true));
    goods.push_back(make_tuple("耳机", 199.9, 200, true));
    goods.push_back(make_tuple("充电器", 49.9, 500, false));
    
    // 遍历商品列表
    for (const auto& g : goods) {
        cout << "商品:" << get<0<(g) 
             << ",单价:" << get<1<(g)
             << ",库存:" << get<2<(g)
             << ",是否上架:" << boolalpha << get<3>(g) << endl;
    }
    
    return 0;
}
        

场景 3:与pair配合使用(多维度扩展)


#include <iostream>
#include <tuple>
#include <vector>
#include <string>
using namespace std;

int main() {
    // tuple中嵌套pair,实现更复杂的复合数据
    tuple<pair<int, string>, float, string> t(
        make_pair(106, "吴九"), 
        90.0, 
        "高三(1)班"
    );
    
    // 访问嵌套的pair
    cout << "学号:" << get<0>(t).first << endl;
    cout << "姓名:" << get<0>(t).second << endl;
    cout << "成绩:" << get<1>(t) << endl;
    cout << "班级:" << get<2>(t) << endl;
    
    return 0;
}
        

四、注意事项

五、总结

本教程全面讲解了 C++ pair 和 tuple 的核心概念、初始化、访问方式及典型应用。掌握这两种轻量级复合类型,能大幅简化多数据聚合、多值返回等场景的代码实现,是 C++ 标准库使用的核心技能之一。


返回顶部